package net.sf.rose.business.service.function;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.rose.business.bean.database.DataTypeMetaBean;
import net.sf.rose.business.bean.database.FieldMetaBean;
import net.sf.rose.business.bean.database.TableMetaBean;

public class Mysql implements Jdbc {

	private Map<String, DataTypeMetaBean> dataTypeMap = null;

	/**
	 * 功能:加载数据库字段的定义列表
	 * @param map  数据库字段的定义
	 */
	public void setDataTypeMetaBeans(Map<String, DataTypeMetaBean> map) {
		this.dataTypeMap = map;
	}

	/**
	 * 功能:根据新旧数据库定义，生成数据库的更新SQL语句
	 * @param map  新的数据库定义
	 * @param bak  旧的数据库定义
	 * @return 返回SQL语句列表
	 */
	@Override
	public List<String> getUpdateSql(Map<String, TableMetaBean> map, Map<String, TableMetaBean> bak) {
		List<String> list = new ArrayList<String>();
		for (TableMetaBean table : map.values()) {
			TableMetaBean old = bak.get(table.getName());
			list.add(old == null ? this.getSQL(table) : this.getSQL(table, old));
		}
		return list;
	}

	private String getSQL(TableMetaBean table) {
		StringBuilder sql = new StringBuilder();
		if (table.getFields() != null) {
			// 遍历每一个字段的定义，创建SQL语句
			for (FieldMetaBean field : table.getFields()) {
				sql.append(field.getName()).append(" ");
				String type = this.dataTypeMap.get(field.getType()).getDbType();
				sql.append(type);
				if (field.getSize() != null) {
					sql.append('(').append(field.getSize()).append(") ");
				}
				if (field.isPk()) {
					sql.append(" primary key");
				}
				if (!field.isCanNull()) {
					sql.append(" not null");
				}
				if (field.getDefaultValue() != null) {
					sql.append(" default ").append(field.getDefaultValue());
				}
				sql.append(",\n");
			}
		}
		// 如果至少有一个字段
		if (sql.length() > 0) {
			sql.insert(0, "create table " + table.getName() + "(\n");
			sql.deleteCharAt(sql.length() - 2);
			sql.append(")");
			return sql.toString();
		} else {
			return null;
		}
	}

	private String getSQL(TableMetaBean table, TableMetaBean bak) {
		StringBuilder sql = new StringBuilder();
		// 将所有旧定义的表字段信息存在Map类中
		Map<String, FieldMetaBean> map = new HashMap<String, FieldMetaBean>();
		if (bak.getFields() != null) {
			for (FieldMetaBean field : bak.getFields()) {
				map.put(field.getName(), field);
			}
		}
		// 遍历所有新定义的表字段数据
		for (FieldMetaBean field : table.getFields()) {
			// 从旧表中取出与之同名的字段定义，生成SQL语句并同时删除旧表中已使用过的字段定义
			getSQL(sql, field, map.remove(field.getName()));
		}
		// 遍历所有旧表中有，新表定义中没有的字段，生成删除字段的SQL语句
		for (FieldMetaBean field : map.values()) {
			sql.append(" drop column ").append(field.getName()).append(",\n");
		}
		// 如果至少有一个字段更新
		if (sql.length() > 0) {
			sql.insert(0, "alter table " + table.getName() + '\n');
			sql.deleteCharAt(sql.length() - 2);
			// sql.append(";");
			return sql.toString();
		} else {
			return null;
		}
	}

	/**
	 * 功能:创建数据库更新某个表结构的SQL语句
	 * <p> 如果返回空值，则不需要执行此SQL语句
	 * @param sql   SQL语句存储类
	 * @param field 某个表新的字段定义
	 * @param old   某个表旧的字段定义
	 * @return 返回SQL语句
	 */
	private void getSQL(StringBuilder sql, FieldMetaBean field, FieldMetaBean old) {
		// 如果旧表定义中没有这个字段，则添加这个字段定义
		if (old == null) {
			sql.append(" add column ");
			sql.append(field.getName()).append(" ");
			if (field.isPk()) {
				sql.append(" primary key");
			}
		} else {
			// 如果新旧字段的定义完全一致，则不需要生成更新SQL语句
			if (field.equals(old))
				return;
			// 生成更新SQL语句
			sql.append(" change column ").append(old.getName()).append(' ').append(field.getName());
		}
		String type = this.dataTypeMap.get(field.getType()).getDbType();
		sql.append(' ').append(type);
		if (field.getSize() != null) {
			sql.append('(').append(field.getSize()).append(") ");
		}
		if (field.isPk() && !old.isPk()) {
			// 不能重复定义主键
			sql.append(" primary key");
		}
		if (!field.isCanNull()) {
			sql.append(" not null");
		}
		if (field.getDefaultValue() != null) {
			sql.append(" default ").append(field.getDefaultValue());
		}
		sql.append(",\n");
	}

}
